﻿using BW.WMS.WareHouseAllot.Dto.DocCode;
using BW.WMS.WareHouseAllot.Interface.Doccode;
using BW.WMS.WareHouseAllot.Parameter.Input.Doccode;
using BW.WMS.WareHouseAllot.Parameter.Input.GoodsType;
using BW.WMS.WareHouseAllot.Parameter.Output.Doccode;
using BW.WMS.WareHouseAllot.Parameter.Output.GoodsType;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace BW.WMS.WareHouseAllot.Doccode
{
    /// <summary>
    /// 自动生成编码服务
    /// </summary>
    public class DoccodeService : ApplicationService, IDoccodeService
    {
        private readonly IRepository<DoccodeModel> _doccodeRepository;

        public DoccodeService(IRepository<DoccodeModel> DoccodeRepository)
        {
            _doccodeRepository = DoccodeRepository;
        }
        /// <summary>
        /// 添加编码规则
        /// </summary>
        public async Task<DoccodeDto> AddDoccodeAsync(AddDoccodeInput input)
        {
            var doccode = ObjectMapper.Map<AddDoccodeInput, DoccodeModel>(input);

            // 【新增】初始化流水号相关字段
            doccode.CurrentSequence = 0;
            doccode.LastGeneratedDate = null;
            doccode.CreateName = "admin"; // 或从当前用户上下文获取

            await _doccodeRepository.InsertAsync(doccode);
            return ObjectMapper.Map<DoccodeModel, DoccodeDto>(doccode);
        }

        /// <summary>
        /// 更新编码规则
        /// </summary>
        public async Task<DoccodeDto> UpdateDoccodeAsync(Guid id, UpdateDoccodeInput input)
        {
            var doccode = await _doccodeRepository.GetAsync(x => x.Id == id);

            // 【新增】如果规则类型或增长类型改变，重置流水号
            if (doccode.RuleType != input.RuleType || doccode.IncreaseType != input.IncreaseType)
            {
                doccode.CurrentSequence = 0;
                doccode.LastGeneratedDate = null;
            }

            ObjectMapper.Map(input, doccode);
            await _doccodeRepository.UpdateAsync(doccode);
            return ObjectMapper.Map<DoccodeModel, DoccodeDto>(doccode);
        }

        /// <summary>
        /// 获取编码规则列表
        /// </summary>
        public async Task<PagedResultDto<DoccodeOutput>> GetDoccodeAsync()
        {
            var doccode = (await _doccodeRepository.GetListAsync())
                .Where(x => !x.IsDeleted);

            var res = ObjectMapper.Map<IEnumerable<DoccodeModel>, IEnumerable<DoccodeOutput>>(doccode);

            return new PagedResultDto<DoccodeOutput>
            {
                TotalCount = doccode.Count(),
                Items = res.ToList()
            };
        }

        /// <summary>
        /// 删除编码规则
        /// </summary>
        public async Task DeleteDoccodeAsync(Guid id)
        {
            var doccode = await _doccodeRepository.GetAsync(x => x.Id == id);
            doccode.IsDeleted = true;
            await _doccodeRepository.UpdateAsync(doccode);
        }

        /// <summary>
        /// 【新增】根据业务名称自动生成编码
        /// </summary>
        public async Task<string> GenerateCodeAsync(string serviceName)
        {
            // 1. 获取编码规则
            var rule = (await _doccodeRepository.GetListAsync())
                .FirstOrDefault(x => x.ServiceName == serviceName && !x.IsDeleted);

            if (rule == null)
                throw new UserFriendlyException($"未找到业务名称 '{serviceName}' 对应的编码规则");

            // 2. 组装前缀
            string code = rule.Prefix ?? "";

            // 3. 组装日期部分
            string dateStr = "";
            if (rule.RuleType == "年")
                dateStr = DateTime.Now.ToString("yyyy");
            else if (rule.RuleType == "年月")
                dateStr = DateTime.Now.ToString("yyyyMM");
            else if (rule.RuleType == "年月日")
                dateStr = DateTime.Now.ToString("yyyyMMdd");

            // 4. 组装连接符
            if (!string.IsNullOrEmpty(rule.Connector))
                code += rule.Connector;

            code += dateStr;

            // 5. 【核心逻辑】生成流水号
            long sequenceNumber = await GetNextSequenceNumberAsync(rule);

            // 6. 格式化流水号
            string serial = sequenceNumber.ToString().PadLeft(rule.CodeNum, '0');

            // 7. 拼接最终编码
            code += serial;

            return code;
        }

        /// <summary>
        /// 【新增】预览编码（不影响流水号）
        /// </summary>
        //public async Task<string> PreviewCodeAsync(AddDoccodeInput input)
        //{
        //    // 1. 组装前缀
        //    string code = input.Prefix ?? "";

        //    // 2. 组装日期部分
        //    string dateStr = "";
        //    if (input.RuleType == "年")
        //        dateStr = DateTime.Now.ToString("yyyy");
        //    else if (input.RuleType == "年月")
        //        dateStr = DateTime.Now.ToString("yyyyMM");
        //    else if (input.RuleType == "年月日")
        //        dateStr = DateTime.Now.ToString("yyyyMMdd");

        //    // 3. 组装连接符
        //    if (!string.IsNullOrEmpty(input.Connector))
        //        code += input.Connector;

        //    code += dateStr;

        //    // 4. 预览时使用默认流水号1
        //    string serial = 1.ToString().PadLeft(input.CodeNum, '0');

        //    // 5. 拼接最终编码
        //    code += serial;

        //    return code;
        //}

        /// <summary>
        /// 【新增】获取所有业务名称
        /// </summary>
        public async Task<List<string>> GetServiceNamesAsync()
        {
            var serviceNames = (await _doccodeRepository.GetListAsync())
                .Where(x => !x.IsDeleted)
                .Select(x => x.ServiceName)
                .Distinct()
                .ToList();
            return serviceNames;
        }

        /// <summary>
        /// 【新增】获取下一个流水号
        /// </summary>
        private async Task<long> GetNextSequenceNumberAsync(DoccodeModel rule)
        {
            // 判断是否需要重置流水号
            bool shouldReset = false;
            DateTime today = DateTime.Today;

            if (rule.IncreaseType == "每日重置" && rule.LastGeneratedDate?.Date != today)
                shouldReset = true;
            else if (rule.IncreaseType == "每月重置" &&
                    (rule.LastGeneratedDate?.Year != today.Year || rule.LastGeneratedDate?.Month != today.Month))
                shouldReset = true;
            else if (rule.IncreaseType == "每年重置" && rule.LastGeneratedDate?.Year != today.Year)
                shouldReset = true;

            long sequenceNumber;
            if (shouldReset)
            {
                sequenceNumber = 1;
            }
            else
            {
                sequenceNumber = rule.CurrentSequence + 1;
            }

            // 更新规则中的流水号和生成日期
            rule.CurrentSequence = sequenceNumber;
            rule.LastGeneratedDate = DateTime.Now;
            await _doccodeRepository.UpdateAsync(rule);

            return sequenceNumber;
        }

        /// <summary>
        /// 根据业务名称获取单据字段列表
        /// </summary>
        public async Task<List<FieldOptionDto>> GetFieldOptionsByServiceNameAsync(string serviceName)
        {
            // 【核心】根据业务名称返回不同的字段列表
            var result = new List<FieldOptionDto>();

            switch (serviceName)
            {
                case "货品类型":
                    result.Add(new FieldOptionDto { FieldName = "GoodsTypeCode", DisplayName = "类型编码(GoodsTypeCode)" });
                    break;
                case "货品信息":
                    result.Add(new FieldOptionDto { FieldName = "GoodsCode", DisplayName = "货品信息编码(GoodsCode)" });
                    break;
                case "部门信息":
                    result.Add(new FieldOptionDto { FieldName = "Depid", DisplayName = "部门编码(Depid)" });
                    break;
                case "仓库盘点信息":
                    result.Add(new FieldOptionDto { FieldName = "Warehouseid", DisplayName = "仓库编码(Warehouseid)" });
                    break;
                case "入库信息":
                    result.Add(new FieldOptionDto { FieldName = "Stockcode", DisplayName = "入库编码(Stockcode)" });
                    break;
                case "销售订单信息":
                    result.Add(new FieldOptionDto { FieldName = "SalesCode", DisplayName = "销售编码(SalesCode)" });
                    break;
                case "销售退货":
                    result.Add(new FieldOptionDto { FieldName = "Returncode", DisplayName = "退货编码(Returncode)" });
                    break;
                case "仓库调拨":
                    result.Add(new FieldOptionDto { FieldName = "AllotCode", DisplayName = "调拨编码(AllotCode)" });
                    break;
                // ... 其他业务类型
                default:
                    // 可以返回空或默认字段
                    break;
            }
            return await Task.FromResult(result);
        }


    }
}
